home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / vim / src / message.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  9KB  |  473 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /*
  10.  * message.c: functions for displaying messages on the command line
  11.  */
  12.  
  13. #include "vim.h"
  14. #include "globals.h"
  15. #define MESSAGE            /* don't include prototype for smsg() */
  16. #include "proto.h"
  17. #include "param.h"
  18.  
  19. static int msg_check_screen __ARGS((void));
  20.  
  21. static int lines_left = -1;            /* lines left for listing */
  22.  
  23. /*
  24.  * msg(s) - displays the string 's' on the status line
  25.  * return TRUE if wait_return not called
  26.  */
  27.     int
  28. msg(s)
  29.     char_u           *s;
  30. {
  31.     if (!screen_valid())            /* terminal not initialized */
  32.     {
  33.         fprintf(stderr, (char *)s);
  34.         fflush(stderr);
  35.         return TRUE;
  36.     }
  37.  
  38.     msg_start();
  39.     if (msg_highlight)            /* actually it is highlighting instead of invert */
  40.         start_highlight();
  41.     msg_outtrans(s, -1);
  42.     if (msg_highlight)
  43.     {
  44.         stop_highlight();
  45.         msg_highlight = FALSE;        /* clear for next call */
  46.     }
  47.     msg_ceol();
  48.     return msg_end();
  49. }
  50.  
  51. #ifndef PROTO        /* automatic prototype generation does not understand this */
  52. /* VARARGS */
  53.     void
  54. smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  55.     char_u        *s;
  56.     long        a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  57. {
  58.     sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  59.     msg(IObuff);
  60. }
  61. #endif
  62.  
  63. /*
  64.  * emsg() - display an error message
  65.  *
  66.  * Rings the bell, if appropriate, and calls message() to do the real work
  67.  *
  68.  * return TRUE if wait_return not called
  69.  */
  70.     int
  71. emsg(s)
  72.     char_u           *s;
  73. {
  74.     if (p_eb)
  75.         beep();                    /* also includes flush_buffers() */
  76.     else
  77.         flush_buffers(FALSE);    /* flush internal buffers */
  78.     (void)set_highlight('e');    /* set highlight mode for error messages */
  79.     msg_highlight = TRUE;
  80. /*
  81.  * Msg returns TRUE if wait_return() was not called.
  82.  * In that case may call sleep() to give the user a chance to read the message.
  83.  * Don't call sleep() if dont_sleep is set.
  84.  */
  85.     if (msg(s))
  86.     {
  87.         if (dont_sleep)
  88.         {
  89.             msg_outchar('\n');    /* one message per line, don't overwrite */
  90.             cmdline_row = msg_row;
  91.             need_wait_return = TRUE;
  92.         }
  93.         else
  94.             sleep(1);            /* give the user a chance to read the message */
  95.         return TRUE;
  96.     }
  97.     return FALSE;
  98. }
  99.  
  100.     int
  101. emsg2(s, a1)
  102.     char_u *s, *a1;
  103. {
  104.     sprintf((char *)IObuff, (char *)s, (char *)a1);
  105.     return emsg(IObuff);
  106. }
  107.  
  108. /*
  109.  * wait for the user to hit a key (normally a return)
  110.  * if 'redraw' is TRUE, clear and redraw the screen
  111.  * if 'redraw' is FALSE, just redraw the screen
  112.  * if 'redraw' is -1, don't redraw at all
  113.  */
  114.     void
  115. wait_return(redraw)
  116.     int        redraw;
  117. {
  118.     int                c;
  119.     int                oldState;
  120.     int                tmpState;
  121.  
  122. /*
  123.  * With the global command (and some others) we only need one return at the
  124.  * end. Adjust cmdline_row to avoid the next message overwriting the last one.
  125.  */
  126.     if (no_wait_return)
  127.     {
  128.         need_wait_return = TRUE;
  129.         cmdline_row = msg_row;
  130.         if (!termcap_active)
  131.             starttermcap();
  132.         return;
  133.     }
  134.     need_wait_return = FALSE;
  135.     lines_left = -1;
  136.     oldState = State;
  137.     State = HITRETURN;
  138.     if (got_int)
  139.         msg_outstr((char_u *)"Interrupt: ");
  140.  
  141.     (void)set_highlight('r');
  142.     start_highlight();
  143. #ifdef ORG_HITRETURN
  144.     msg_outstr("Press RETURN to continue");
  145.     stop_highlight();
  146.     do {
  147.         c = vgetc();
  148.     } while (strchr("\r\n: ", c) == NULL);
  149.     if (c == ':')                     /* this can vi too (but not always!) */
  150.         stuffcharReadbuff(c);
  151. #else
  152.     msg_outstr((char_u *)"Press RETURN or enter command to continue");
  153.     stop_highlight();
  154.     do
  155.     {
  156.         c = vgetc();
  157.         got_int = FALSE;
  158.     } while (c == Ctrl('C'));
  159.     breakcheck();
  160.     if (strchr("\r\n ", c) == NULL)
  161.         stuffcharReadbuff(c);
  162. #endif
  163.  
  164.     /*
  165.      * If the user hits ':' we get a command line from the next line.
  166.      */
  167.     if (c == ':')
  168.         cmdline_row = msg_row;
  169.  
  170.     if (!termcap_active)            /* start termcap before redrawing */
  171.         starttermcap();
  172.  
  173. /*
  174.  * If the window size changed set_winsize() will redraw the screen.
  175.  * Otherwise the screen is only redrawn if 'redraw' is set and no ':' typed.
  176.  */
  177.     tmpState = State;
  178.     State = oldState;                /* restore State before set_winsize */
  179.     msg_check();
  180.     if (tmpState == SETWSIZE)        /* got resize event while in vgetc() */
  181.         set_winsize(0, 0, FALSE);
  182.     else if (redraw == TRUE)
  183.     {
  184.         if (c == ':')
  185.             must_redraw = CLEAR;
  186.         else
  187.             updateScreen(CLEAR);
  188.     }
  189.     else if (msg_scrolled && c != ':' && redraw != -1)
  190.         updateScreen(VALID);
  191.  
  192.     if (c == ':')
  193.         skip_redraw = TRUE;            /* skip redraw once */
  194. }
  195.  
  196. /*
  197.  * Prepare for outputting characters in the command line.
  198.  */
  199.     void
  200. msg_start()
  201. {
  202.     did_msg = TRUE;                    /* for doglob() */
  203.     keep_msg = NULL;                /* don't display old message now */
  204.     msg_pos(cmdline_row, 0);
  205.     cursor_off();
  206.     lines_left = cmdline_row;
  207. }
  208.  
  209. /*
  210.  * Move message position. This should always be used after moving the cursor.
  211.  * Use negative value if row or col does not have to be changed.
  212.  */
  213.     void
  214. msg_pos(row, col)
  215.     int        row, col;
  216. {
  217.     if (row >= 0)
  218.         msg_row = row;
  219.     if (col >= 0)
  220.         msg_col = col;
  221.     screen_start();
  222. }
  223.  
  224.     void
  225. msg_outchar(c)
  226.     int        c;
  227. {
  228.     char_u        buf[2];
  229.  
  230.     buf[0] = c;
  231.     buf[1] = NUL;
  232.     msg_outstr(buf);
  233. }
  234.  
  235.     void
  236. msg_outnum(n)
  237.     long        n;
  238. {
  239.     char_u        buf[20];
  240.  
  241.     sprintf((char *)buf, "%ld", n);
  242.     msg_outstr(buf);
  243. }
  244.  
  245. /*
  246.  * output 'len' characters in 'str' (including NULs) with translation
  247.  * if 'len' is -1, output upto a NUL character
  248.  * return the number of characters it takes on the screen
  249.  */
  250.     int
  251. msg_outtrans(str, len)
  252.     register char_u *str;
  253.     register int   len;
  254. {
  255.     int retval = 0;
  256.  
  257.     if (len == -1)
  258.         len = STRLEN(str);
  259.     while (--len >= 0)
  260.     {
  261.         msg_outstr(transchar(*str));
  262.         retval += charsize(*str);
  263.         ++str;
  264.     }
  265.     return retval;
  266. }
  267.  
  268. /*
  269.  * print line for :p command
  270.  */
  271.     void
  272. msg_prt_line(s)
  273.     char_u           *s;
  274. {
  275.     register int    si = 0;
  276.     register int    c;
  277.     register int    col = 0;
  278.  
  279.     int             n_extra = 0;
  280.     int             n_spaces = 0;
  281.     char_u            *p = NULL;            /* init to make SASC shut up */
  282.     int             n;
  283.  
  284.     for (;;)
  285.     {
  286.         if (n_extra)
  287.         {
  288.             --n_extra;
  289.             c = *p++;
  290.         }
  291.         else if (n_spaces)
  292.         {
  293.             --n_spaces;
  294.             c = ' ';
  295.         }
  296.         else
  297.         {
  298.             c = s[si++];
  299.             if (c == TAB && !curwin->w_p_list)
  300.             {
  301.                 /* tab amount depends on current column */
  302.                 n_spaces = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
  303.                 c = ' ';
  304.             }
  305.             else if (c == NUL && curwin->w_p_list)
  306.             {
  307.                 p = (char_u *)"";
  308.                 n_extra = 1;
  309.                 c = '$';
  310.             }
  311.             else if (c != NUL && (n = charsize(c)) > 1)
  312.             {
  313.                 n_extra = n - 1;
  314.                 p = transchar(c);
  315.                 c = *p++;
  316.             }
  317.         }
  318.  
  319.         if (c == NUL)
  320.             break;
  321.  
  322.         msg_outchar(c);
  323.         col++;
  324.     }
  325. }
  326.  
  327. /*
  328.  * output a string to the screen at position msg_row, msg_col
  329.  * Update msg_row and msg_col for the next message.
  330.  */
  331.     void
  332. msg_outstr(s)
  333.     char_u        *s;
  334. {
  335.     int        c;
  336.  
  337.     /*
  338.      * if there is no valid screen, use fprintf so we can see error messages
  339.      */
  340.     if (!msg_check_screen())
  341.     {
  342.         fprintf(stderr, (char *)s);
  343.         return;
  344.     }
  345.  
  346.     while (*s)
  347.     {
  348.         /*
  349.          * the screen is scrolled up when:
  350.          * - When outputting a newline in the last row
  351.          * - when outputting a character in the last column of the last row
  352.          *   (some terminals scroll automatically, some don't. To avoid problems
  353.          *   we scroll ourselves)
  354.          */
  355.         if (msg_row >= Rows - 1 && (*s == '\n' || msg_col >= Columns - 1))
  356.         {
  357.             screen_del_lines(0, 0, 1, (int)Rows);        /* always works */
  358.             msg_row = Rows - 2;
  359.             if (msg_col >= Columns)        /* can happen after screen resize */
  360.                 msg_col = Columns - 1;
  361.             ++msg_scrolled;
  362.             if (cmdline_row > 0)
  363.                 --cmdline_row;
  364.             /*
  365.              * if screen is completely filled wait for a character
  366.              */
  367.             if (p_more && --lines_left == 0)
  368.             {
  369.                 windgoto((int)Rows - 1, 0);
  370.                 outstr((char_u *)"-- more --");
  371.                 c = vgetc();
  372.                 if (c == CR || c == NL)
  373.                     lines_left = 1;
  374.                 else if (c == 'q' || c == Ctrl('C'))
  375.                     got_int = TRUE;
  376.                 else
  377.                     lines_left = Rows - 1;
  378.                 outstr((char_u *)"\r          ");
  379.             }
  380.             screen_start();
  381.         }
  382.         if (*s == '\n')
  383.         {
  384.             msg_col = 0;
  385.             ++msg_row;
  386.         }
  387.         else
  388.         {
  389.             screen_outchar(*s, msg_row, msg_col);
  390.             if (++msg_col >= Columns)
  391.             {
  392.                 msg_col = 0;
  393.                 ++msg_row;
  394.             }
  395.         }
  396.         ++s;
  397.     }
  398. }
  399.  
  400. /*
  401.  * msg_check_screen - check if the screen is initialized.
  402.  * Also check msg_row and msg_col, if they are too big it may cause a crash.
  403.  */
  404.     static int
  405. msg_check_screen()
  406. {
  407.     if (!screen_valid())
  408.         return FALSE;
  409.     
  410.     if (msg_row >= Rows)
  411.         msg_row = Rows - 1;
  412.     if (msg_col >= Columns)
  413.         msg_col = Columns - 1;
  414.     return TRUE;
  415. }
  416.  
  417. /*
  418.  * clear from current message position to end of screen
  419.  * Note: msg_col is not updated, so we remember the end of the message
  420.  * for msg_check().
  421.  */
  422.     void
  423. msg_ceol()
  424. {
  425.     if (!msg_check_screen())
  426.         return;
  427.     screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ');
  428.     screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ');
  429. }
  430.  
  431. /*
  432.  * end putting a message on the screen
  433.  * call wait_return if the message does not fit in the available space
  434.  * return TRUE if wait_return not called.
  435.  */
  436.     int
  437. msg_end()
  438. {
  439.     lines_left = -1;
  440.     /*
  441.      * if the string is larger than the window,
  442.      * or the ruler option is set and we run into it,
  443.      * we have to redraw the window.
  444.      * Do not do this if we are abandoning the file or editing the command line.
  445.      */
  446.     if (!exiting && msg_check() && State != CMDLINE)
  447.     {
  448.         msg_outchar('\n');
  449.         wait_return(FALSE);
  450.         return FALSE;
  451.     }
  452.     flushbuf();
  453.     return TRUE;
  454. }
  455.  
  456. /*
  457.  * If the written message has caused the screen to scroll up, or if we
  458.  * run into the shown command or ruler, we have to redraw the window later.
  459.  */
  460.     int
  461. msg_check()
  462. {
  463.     lines_left = -1;
  464.     if (msg_scrolled || (msg_row == Rows - 1 && msg_col >= sc_col))
  465.     {
  466.         if (must_redraw < NOT_VALID)
  467.             must_redraw = NOT_VALID;
  468.         redraw_cmdline = TRUE;
  469.         return TRUE;
  470.     }
  471.     return FALSE;
  472. }
  473.